package com.market.member.service.impl;

import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.block.common.bean.SessionBean;
import com.block.common.constant.AppRspCodeConstant;
import com.block.common.constant.RedisKeyConstant;
import com.block.common.model.dto.CountInfoDTO;
import com.block.common.service.IChannelCommonService;
import com.block.common.service.IMemberCommonService;
import com.block.common.service.LogFactory;
import com.block.common.vo.ResponseVo;
import com.block.db.entity.*;
import com.block.db.mapper.MemberAuthInfoMapper;
import com.block.db.mapper.MemberBaseInfoMapper;
import com.block.db.mapper.MemberSourceInfoMapper;
import com.market.member.config.AuthVerifyConfig;
import com.market.member.enums.AuthStatusEnum;
import com.market.member.factory.AuthPlatformFactory;
import com.market.member.model.dto.AuthRequestDTO;
import com.market.member.model.result.AuthRequestResult;
import com.market.member.model.vo.AuthInfoVO;
import com.market.member.service.IMemberAuthConfigInfoService;
import com.market.member.service.IMemberAuthInfoService;
import com.market.member.service.IMemberAuthRecordInfoService;
import com.market.member.service.IMemberBaseInfoService;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * <p>
 * 用户认证信息 服务实现类
 * </p>
 *
 * @author 
 * @since 2023-08-09
 */
@Service
public class MemberAuthInfoServiceImpl extends ServiceImpl<MemberAuthInfoMapper, MemberAuthInfo> implements IMemberAuthInfoService {

    private static final Logger log = LogFactory.getCommLog();

    @Resource
    MemberBaseInfoMapper memberBaseInfoMapper;
    @Autowired
    IMemberBaseInfoService memberBaseInfoService;
    @Resource
    MemberSourceInfoMapper memberSourceInfoMapper;
    @Autowired
    IMemberAuthRecordInfoService memberAuthRecordInfoService;
    @Autowired
    AuthVerifyConfig authVerifyConfig;
    @Autowired
    IMemberAuthConfigInfoService memberAuthConfigInfoService;
    @Autowired
    IMemberCommonService memberCommonService;
    @Autowired
    IChannelCommonService channelCommonService;
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    public ResponseVo updateAuthInfo(SessionBean sessionBean, String realname, String idCard) {

        Long uid = sessionBean.getUid();
        MemberAuthInfo  memberAuthInfo = this.baseMapper.getEntityInfoByUid(sessionBean.getUid());
        if (ObjectUtil.isEmpty(memberAuthInfo)){
            // 认证信息为空
            memberAuthInfo  = new MemberAuthInfo();
            memberAuthInfo.setUid(sessionBean.getUid());
            memberAuthInfo.setRealname(realname);
            memberAuthInfo.setIdcard(idCard);
            memberAuthInfo.setAuthStatus(AuthStatusEnum.SUCCESS.getValue());
            boolean save = this.save(memberAuthInfo);
            log.info("【更新实名信息】保存实名信息【save】{}【uid】{}", save, uid);
            if (!save){
                return new ResponseVo(AppRspCodeConstant.ACTION_ERROR, "保存失败，请重试");
            }

            MemberBaseInfo memberBaseInfo = new MemberBaseInfo();
            memberBaseInfo.setUid(sessionBean.getUid());
            memberBaseInfo.setUsername(DesensitizedUtil.chineseName(realname));
            memberBaseInfo.setAuthFlag(1);
            memberBaseInfo.setUpdateTime(LocalDateTime.now());
            boolean b = memberBaseInfoService.updateById(memberBaseInfo);

            CountInfoDTO countInfoDTO = new CountInfoDTO(sessionBean.getChannelCode());
            countInfoDTO.setAuthCount(1);
            channelCommonService.updateChannelCount(countInfoDTO);
        }
//        else{
//            // 认证信息不为空，判断是否可以更新实名认证信息
//            MemberBaseInfo memberBaseInfo = memberBaseInfoMapper.getMemberInfoByUidLock(uid);
//            if (ObjectUtil.equals(memberBaseInfo.getAuthFlag(), Integer.valueOf(1)) &&
//                    ObjectUtil.equals(memberAuthInfo.getAuthStatus(), AuthStatusEnum.SUCCESS.getValue())){
//                // 已实名认证完成
//                log.info("【更新实名信息】已实名，不可操作【uid】{}", uid);
//                return new ResponseVo(AppRspCodeConstant.ACTION_ERROR, "已实名认证，不能进行操作！");
//            }
//        }

        // 更新实名认证信息
//        MemberAuthInfo updateEntity = new MemberAuthInfo();
//        updateEntity.setUid(uid);
//        updateEntity.setRealname(realname);
//        updateEntity.setIdcard(idCard);
//        updateEntity.setAuthStatus(AuthStatusEnum.INIT.getValue());
//        boolean updateRes = this.updateById(updateEntity);
//        log.info("【更新实名信息】更新实名信息【updateRes】{}【uid】{}", updateRes, uid);

        return new ResponseVo(AppRspCodeConstant.SUCCESS);
    }

    @Override
    public ResponseVo getAuthInfo(Long uid) {

        AuthInfoVO authInfoVO = new AuthInfoVO();

        // 验证资质信息
        MemberSourceInfo memberSourceInfo = memberSourceInfoMapper.getEntityByUidLock(uid);
        if (ObjectUtil.isEmpty(memberSourceInfo)){
            authInfoVO.setSourceFlag(0);
        }else{
            authInfoVO.setSourceFlag(1);
        }

        MemberBaseInfo memberBaseInfo = memberBaseInfoMapper.getMemberInfoByUidLock(uid);
        authInfoVO.setMobile(DesensitizedUtil.mobilePhone(memberBaseInfo.getMobile()));


        MemberAuthInfo memberAuthInfo = this.baseMapper.getEntityInfoByUid(uid);
        if (ObjectUtil.isEmpty(memberAuthInfo)){
            // 认证信息
            authInfoVO.setAuthFlag(0);
        }else{
            Integer authFlag = StrUtil.equals(memberAuthInfo.getAuthStatus(), AuthStatusEnum.SUCCESS.getValue())?1:0;
            authInfoVO.setAuthFlag(authFlag);
            if (ObjectUtil.equals(authFlag, Integer.valueOf(1))){
                authInfoVO.setRealname(DesensitizedUtil.chineseName(memberAuthInfo.getRealname()));
                authInfoVO.setIdcard(DesensitizedUtil.idCardNum(memberAuthInfo.getIdcard(), 3, 2));
            }

            // 人脸认证信息
            Integer faceFlag = StrUtil.equals(memberAuthInfo.getFaceStatus(), AuthStatusEnum.SUCCESS.getValue())?1:0;
            authInfoVO.setFaceFlag(faceFlag);
        }

        return new ResponseVo(AppRspCodeConstant.SUCCESS, authInfoVO);
    }

    /**
     * 查询认证配置信息
     * @param uid
     * @param reqData
     * @return
     */
    @Override
    public ResponseVo getAuthConfigInfo(Long uid, String reqData) {

        // 查询用户是否已经认证通过
        MemberAuthInfo  memberAuthInfo = this.baseMapper.getEntityInfoByUid(uid);
        if (ObjectUtil.isEmpty(memberAuthInfo)){
            // 认证信息为空
            memberAuthInfo  = new MemberAuthInfo();
            memberAuthInfo.setUid(uid);
            memberAuthInfo.setFaceStatus(AuthStatusEnum.INIT.getValue());
            boolean save = this.save(memberAuthInfo);
            log.info("【请求实人认证】保存实名记录【save】{}【uid】{}", save, uid);
            if (!save){
                return new ResponseVo(AppRspCodeConstant.ACTION_ERROR, "保存失败，请重试");
            }
        }else{
            // 认证信息不为空，判断是否可以更新实名认证信息
            MemberBaseInfo memberBaseInfo = memberBaseInfoMapper.getMemberInfoByUidLock(uid);
            if (ObjectUtil.equals(memberBaseInfo.getFaceFlag(), Integer.valueOf(1)) &&
                    ObjectUtil.equals(memberAuthInfo.getFaceStatus(), AuthStatusEnum.SUCCESS.getValue())){
                // 已实名认证完成
                log.info("【请求实人认证】已实名，不可操作【uid】{}", uid);
                return new ResponseVo(AppRspCodeConstant.ACTION_ERROR, "已实名认证，不能进行操作！");
            }
        }

        // 查询配置信息，生成请求记录
        MemberAuthConfigInfo authConfigInfo = memberAuthConfigInfoService.getConfigInfoByPlatform(authVerifyConfig.getPlatform());
        MemberAuthRecordInfo memberAuthRecordInfo = memberAuthRecordInfoService.saveRecordInfo(authConfigInfo, uid, reqData);

        // 生成认证记录
        AuthRequestDTO authRequestDTO = new AuthRequestDTO();
        authRequestDTO.setReqData(reqData);
        authRequestDTO.setOrderNo(String.valueOf(memberAuthRecordInfo.getId()));
        authRequestDTO.setCertName(memberAuthInfo.getRealname());
        authRequestDTO.setCertNo(memberAuthInfo.getIdcard());

        try {
            // 请求具体的服务，得到返回结果
            AuthRequestResult authRequestResult =
                    AuthPlatformFactory.getService(authConfigInfo.getPlatform()).getAuthConfigInfo(authRequestDTO, authConfigInfo);
            log.info("【请求实人认证】请求平台结果【authRequestResult】{}", JSON.toJSONString(authRequestResult));
            // 更新用户的返回结果
            if (!authRequestResult.isSuccess()){
                // TODO: 2023/8/13 消息通知
                MemberAuthRecordInfo updateRecord = new MemberAuthRecordInfo();
                updateRecord.setId(memberAuthRecordInfo.getId());
                updateRecord.setStatus(AuthStatusEnum.FAILED.getValue());
                updateRecord.setMessage(authRequestResult.getMessage());
                updateRecord.setCode(authRequestResult.getCode());
                memberAuthRecordInfoService.updateById(updateRecord);

                if (StrUtil.equals(authRequestResult.getCode(), "401")){
                    return new ResponseVo(AppRspCodeConstant.GET_FACE_CONFIG_NAME_IDCAED, "身份证/姓名错误");
                }
                return new ResponseVo(AppRspCodeConstant.SYS_EXCEPTION, "获取认证配置信息失败");
            }

            MemberAuthRecordInfo updateEntity = new MemberAuthRecordInfo();
            updateEntity.setId(memberAuthRecordInfo.getId());
            updateEntity.setStatus(AuthStatusEnum.WAITING.getValue());
            updateEntity.setOutOrderNo(authRequestResult.getOutOrderNo());
            updateEntity.setRequestResult(authRequestResult.getResultInfo());
            boolean updateRes = memberAuthRecordInfoService.updateById(updateEntity);
            log.info("【请求实人认证】更新请求结果【updateRes】{}【authRequestResult】{}", updateRes, JSON.toJSONString(authRequestResult));
            if (!updateRes){
                // TODO: 2023/8/13 消息通知
                return new ResponseVo(AppRspCodeConstant.SYS_EXCEPTION, "获取配置信息异常");
            }

            JSONObject returnData = new JSONObject();
            returnData.put("orderNo", String.valueOf(memberAuthRecordInfo.getId()));
            returnData.put("resultData", authRequestResult.getResultData());
            return new ResponseVo(AppRspCodeConstant.SUCCESS, returnData);
        }catch (Exception exception){
            // TODO: 2023/8/13 消息通知
            log.error("【请求实人认证】操作异常", exception);
        }
        return new ResponseVo(AppRspCodeConstant.SYS_EXCEPTION, "操作失败，请重试");
    }

    /**
     * 查询认证结果
     * @param uid
     * @param orderNo
     * @return
     */
    @Override
    public ResponseVo queryAuthResult(Long uid, String orderNo) {

        // 查询认证记录
        //
        boolean queryRes = memberAuthRecordInfoService.queryAuthVerifyResult(orderNo);

        AuthInfoVO authInfoVO = new AuthInfoVO();
        if (queryRes){
            MemberAuthInfo memberAuthInfo = this.baseMapper.getEntityInfoByUid(uid);
            if (ObjectUtil.isEmpty(memberAuthInfo)){
                authInfoVO.setAuthFlag(0);
                authInfoVO.setFaceFlag(0);
            }else{

                Integer authFlag = StrUtil.equals(memberAuthInfo.getAuthStatus(), AuthStatusEnum.SUCCESS.getValue())?1:0;
                Integer faceFlag = StrUtil.equals(memberAuthInfo.getFaceStatus(), AuthStatusEnum.SUCCESS.getValue())?1:0;
                authInfoVO.setAuthFlag(authFlag);
                authInfoVO.setFaceFlag(faceFlag);
                if (ObjectUtil.equals(authFlag, Integer.valueOf(1))){
                    authInfoVO.setRealname(DesensitizedUtil.chineseName(memberAuthInfo.getRealname()));
                    authInfoVO.setIdcard(DesensitizedUtil.idCardNum(memberAuthInfo.getIdcard(), 3, 2));
                }
            }
        }else{
            authInfoVO.setAuthFlag(0);
            authInfoVO.setFaceFlag(0);
        }

        JSONObject returnData = JSON.parseObject(JSON.toJSONString(authInfoVO));
        return new ResponseVo(AppRspCodeConstant.SUCCESS, returnData);
    }

}
